package cn.com.ejiakanghu.web;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.com.ejiakanghu.annotation.LoginUser;
import cn.com.ejiakanghu.core.utils.RespUtil;
import cn.com.ejiakanghu.core.vo.BaseResult;
import cn.com.ejiakanghu.dto.UserInfo;
import cn.com.ejiakanghu.dto.UserRoleData;
import cn.com.ejiakanghu.dto.WxLoginInfo;
import cn.com.ejiakanghu.service.UserManager;
import cn.com.ejiakanghu.service.UserTokenManager;
import cn.com.ejiakanghu.wx.config.WeixinConfig;
import com.ejiakanghu.wxutil.WXBizDataCrypt;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.util.*;
import org.linlinjava.litemall.db.dao.AgedmallVipLevelMapper;
import org.linlinjava.litemall.db.domain.AgedmallAgent;
import org.linlinjava.litemall.db.domain.AgedmallVipLevel;
import org.linlinjava.litemall.db.domain.LitemallUser;
import org.linlinjava.litemall.db.service.AgedmallAgentService;
import org.linlinjava.litemall.db.service.AgedmallUserInfoService;
import org.linlinjava.litemall.db.service.LitemallUserService;
import org.linlinjava.litemall.db.util.EnumUserRegisterSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.linlinjava.litemall.db.util.DateUtil.DATE_TIME_FORMATTER;


/**
 * 鉴权服务
 */
@RestController
@RequestMapping("/wx/auth")
@Validated
public class WxAuthController {
    private Logger logger = LoggerFactory.getLogger(WxAuthController.class);

    @Autowired
    private LitemallUserService userService;

    @Autowired
    private WxMaService wxService;

    @Autowired
    private AgedmallUserInfoService agedmallUserInfoService;
    @Autowired
    private AgedmallAgentService agedmallAgentService;
    @Autowired
    private UserManager userManager;
    @Resource
    private AgedmallVipLevelMapper agedmallVipLevelMapper;


    /**
     * @api {post} /wx/auth/loginByWeixin 微信登录
     * @apiGroup 鉴权服务
     * @apiVersion 0.1.0
     * @apiDescription 用户授权微信手机号登录
     * @apiSuccess {Object} Object
     * @apiSuccessExample {json} Success-Response:
     * { "msg": "成功", "code":0, "data": {} }
     */
    @PostMapping("/loginByWeixin")
    public BaseResult loginByWeixin(WxLoginInfo wxLoginInfo, HttpServletRequest request) {
        String code = wxLoginInfo.getCode();
        UserInfo userInfo = wxLoginInfo.getUserInfo();
        if (code == null || userInfo == null) {
            return RespUtil.badArgument();
        }

        String sessionKey = null;
        String openId = null;
        try {
            WxMaJscode2SessionResult result = this.wxService.getUserService().getSessionInfo(code);
            sessionKey = result.getSessionKey();
            openId = result.getOpenid();
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (sessionKey == null || openId == null) {
            return RespUtil.fail();
        }

        String mobile = null;
        String iv = wxLoginInfo.getIv();
        if (!StringUtils.isEmpty(iv)) {
            WXBizDataCrypt biz = new WXBizDataCrypt(WeixinConfig.ONLINE_LEASE_MINI_APP_ID, sessionKey);
            String encryptedData = wxLoginInfo.getData();
            String data = biz.decryptData(encryptedData, iv);
            logger.info("微信登录数据为:{}",data);
            Map<String, Object> dataMap = JacksonUtil.gson.fromJson(data, Map.class);
            //Map<String, Object> jsonMap = JacksonUtil.gson.fromJson(data, Map.class);
            mobile = dataMap.get("phoneNumber").toString();
        }

        LitemallUser user = null;
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(mobile)) {
            user = userService.queryOneByMobile(mobile);
        } else {
            user = userService.queryByOid(openId);
        }

        if (user == null) {
            user = new LitemallUser();
            user.setUsername(openId);
            user.setPassword(openId);
            user.setWeixinOpenid(openId);
            user.setAvatar(userInfo.getAvatarUrl());
            user.setNickname(userInfo.getNickName());
            user.setGender(userInfo.getGender());
            user.setUserLevel((byte) 0);
            user.setStatus((byte) 0);
            user.setLastLoginTime(LocalDateTime.now());
            user.setLastLoginIp(IpUtil.getIpAddr(request));
            user.setSessionKey(sessionKey);
            user.setCreateSource(EnumUserRegisterSource.WXMINI.getSource());
            user.setMobile(mobile);

            userService.add(user);
            agedmallUserInfoService.add(user.getId());

            userInfo.setUid(user.getId());
            userInfo.setPhone(user.getMobile());
            userInfo.setSource(user.getCreateSource());
            userInfo.setCreated(user.getAddTime().format(DATE_TIME_FORMATTER));
            userInfo.setNickName(user.getNickname());
            userInfo.setAvatarUrl(user.getAvatar());
            // 新用户发送注册优惠券
//            couponAssignService.assignForRegister(user.getId());
        } else {
            user.setAvatar(userInfo.getAvatarUrl());
            user.setNickname(userInfo.getNickName());
            user.setLastLoginTime(LocalDateTime.now());
            user.setLastLoginIp(IpUtil.getIpAddr(request));
            user.setWeixinOpenid(openId);
            user.setSessionKey(sessionKey);
            userService.updateById(user);

            userInfo.setUid(user.getId());
            userInfo.setPhone(user.getMobile());
            userInfo.setSource(user.getCreateSource());
            userInfo.setCreated(user.getAddTime().format(DATE_TIME_FORMATTER));
            userInfo.setNickName(user.getNickname());
            userInfo.setAvatarUrl(user.getAvatar());
        }

        UserRoleData roleData = userManager.getUserRoles(user.getId());
        String rolesStr = roleData.getRoles();
        userInfo.setRoles(rolesStr);
        AgedmallVipLevel vipLevel = agedmallVipLevelMapper.selectByPrimaryKey(user.getUserLevel().intValue());
        userInfo.setVipLevel(vipLevel!=null?vipLevel.getVipLevel():0);
        // token
        String token = UserTokenManager.generateToken(user.getId());

        Map<Object, Object> result = new HashMap<Object, Object>();
        result.put("token", token);
        result.put("userInfo", userInfo);
        return RespUtil.success(result);
    }


    /**
     * @api {get} /wx/auth/bindPhone 微信绑定手机号
     * @apiGroup 鉴权服务
     * @apiVersion 0.1.0
     * @apiDescription 用户授权绑定手机号
     * @apiSuccess {Object} Object
     * @apiSuccessExample {json} Success-Response:
     * { "msg": "成功", "code":0, "data": {} }
     */
    @PostMapping("bindPhone")
    public Object bindPhone(@LoginUser Integer userId, @RequestBody String body) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        LitemallUser user = userService.findById(userId);
        String encryptedData = JacksonUtil.parseString(body, "encryptedData");
        String iv = JacksonUtil.parseString(body, "iv");
        WxMaPhoneNumberInfo phoneNumberInfo = this.wxService.getUserService().getPhoneNoInfo(user.getSessionKey(), encryptedData, iv);
        String phone = phoneNumberInfo.getPhoneNumber();
        user.setMobile(phone);
        if (userService.updateById(user) == 0) {
            return ResponseUtil.updatedDataFailed();
        }
        return ResponseUtil.ok();
    }

}
